using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;

namespace K3Cloud.WebApi.Core.IoC.Extensions
{
    /// <summary>
    /// 表达式优化器接口
    /// </summary>
    public interface IExpressionOptimizer
    {
        /// <summary>
        /// 优化表达式树
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="expression">原始表达式</param>
        /// <returns>优化后的表达式</returns>
        Expression<Func<T, bool>> Optimize<T>(Expression<Func<T, bool>> expression);

        /// <summary>
        /// 获取最后一次优化的统计信息
        /// </summary>
        OptimizationStats GetLastStats();

        /// <summary>
        /// 添加自定义优化规则
        /// </summary>
        void AddRule(IOptimizationRule rule);

        /// <summary>
        /// 移除优化规则
        /// </summary>
        void RemoveRule(string ruleName);
    }

    /// <summary>
    /// 表达式优化器配置选项
    /// </summary>
    public class ExpressionOptimizerOptions
    {
        /// <summary>是否启用常量折叠</summary>
        public bool EnableConstantFolding { get; set; } = true;

        /// <summary>是否启用冗余移除</summary>
        public bool EnableRedundantRemoval { get; set; } = true;

        /// <summary>是否启用布尔简化</summary>
        public bool EnableBooleanSimplification { get; set; } = true;

        /// <summary>最大优化迭代次数（防止无限循环）</summary>
        public int MaxIterations { get; set; } = 10;

        /// <summary>是否记录优化详情到控制台</summary>
        public bool LogOptimizationDetails { get; set; } = false;

        /// <summary>优化阈值：只优化节点数大于此值的表达式</summary>
        public int OptimizationThreshold { get; set; } = 5;
    }

    /// <summary>
    /// 表达式优化器默认实现
    /// </summary>
    public class ExpressionOptimizer : IExpressionOptimizer
    {
        private readonly List<IOptimizationRule> _rules = new List<IOptimizationRule>();
        private readonly ExpressionOptimizerOptions _options;
        private OptimizationStats? _lastStats;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="options">优化器配置选项</param>
        public ExpressionOptimizer(ExpressionOptimizerOptions? options = null)
        {
            _options = options ?? new ExpressionOptimizerOptions();

            // 注册默认优化规则
            if (_options.EnableConstantFolding)
                _rules.Add(new ConstantFoldingRule());

            if (_options.EnableBooleanSimplification)
                _rules.Add(new BooleanSimplificationRule());

            if (_options.EnableRedundantRemoval)
                _rules.Add(new RedundantRemovalRule());

            // 按优先级排序
            _rules.Sort((a, b) => a.Priority.CompareTo(b.Priority));
        }

        public Expression<Func<T, bool>> Optimize<T>(Expression<Func<T, bool>> expression)
        {
            if (expression == null)
                throw new ArgumentNullException(nameof(expression));

            var sw = Stopwatch.StartNew();

            // 统计原始节点数
            int originalNodeCount = NodeCounterVisitor.CountNodes(expression);

            // 如果节点数小于阈值，不优化
            if (originalNodeCount < _options.OptimizationThreshold)
            {
                _lastStats = new OptimizationStats
                {
                    OriginalNodeCount = originalNodeCount,
                    OptimizedNodeCount = originalNodeCount,
                    ElapsedMilliseconds = sw.Elapsed.TotalMilliseconds,
                    IterationCount = 0
                };
                return expression;
            }

            var stats = new OptimizationStats
            {
                OriginalNodeCount = originalNodeCount
            };

            Expression<Func<T, bool>> optimized = expression;
            int previousNodeCount = originalNodeCount;
            int iteration = 0;

            // 迭代优化，直到无法继续优化或达到最大迭代次数
            while (iteration < _options.MaxIterations)
            {
                iteration++;
                bool hasOptimized = false;

                // 应用每个优化规则
                foreach (var rule in _rules)
                {
                    try
                    {
                        if (rule.CanApply(optimized))
                        {
                            var before = optimized;
                            var result = rule.Apply(optimized);

                            if (result is Expression<Func<T, bool>> typedResult)
                            {
                                optimized = typedResult;

                                // 检查是否真的发生了变化
                                int currentNodeCount = NodeCounterVisitor.CountNodes(optimized);
                                if (currentNodeCount < previousNodeCount)
                                {
                                    hasOptimized = true;
                                    previousNodeCount = currentNodeCount;

                                    if (!stats.OptimizationTypes.Contains(rule.Name))
                                    {
                                        stats.OptimizationTypes.Add(rule.Name);
                                    }

                                    if (_options.LogOptimizationDetails)
                                    {
                                        Console.WriteLine($"[优化器] 应用规则 '{rule.Name}': 节点数 {NodeCounterVisitor.CountNodes(before)} → {currentNodeCount}");
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        // 如果某个规则失败，记录但继续处理其他规则
                        if (_options.LogOptimizationDetails)
                        {
                            Console.WriteLine($"[优化器] 规则 '{rule.Name}' 执行失败: {ex.Message}");
                        }
                    }
                }

                // 如果本次迭代没有优化，退出循环
                if (!hasOptimized)
                    break;
            }

            sw.Stop();

            // 更新统计信息
            stats.OptimizedNodeCount = NodeCounterVisitor.CountNodes(optimized);
            stats.ElapsedMilliseconds = sw.Elapsed.TotalMilliseconds;
            stats.IterationCount = iteration;

            _lastStats = stats;

            if (_options.LogOptimizationDetails && stats.HasOptimized)
            {
                Console.WriteLine($"[优化器] {stats}");
            }

            return optimized;
        }

        public OptimizationStats GetLastStats()
        {
            return _lastStats ?? new OptimizationStats();
        }

        public void AddRule(IOptimizationRule rule)
        {
            if (rule == null)
                throw new ArgumentNullException(nameof(rule));

            if (!_rules.Any(r => r.Name == rule.Name))
            {
                _rules.Add(rule);
                _rules.Sort((a, b) => a.Priority.CompareTo(b.Priority));
            }
        }

        public void RemoveRule(string ruleName)
        {
            _rules.RemoveAll(r => r.Name == ruleName);
        }

        /// <summary>
        /// 获取所有已注册的规则
        /// </summary>
        public IReadOnlyList<IOptimizationRule> GetRules()
        {
            return _rules.AsReadOnly();
        }
    }
}
